import { Subscription, interval, merge, of } from 'rxjs';
import { combineAll, concatMap, delay, map, take, withLatestFrom } from 'rxjs/operators';

import { forkJoin } from 'rxjs';

// 输出容器映射
const outputElements: { [key: string]: HTMLElement } = {};
const subscriptions: { [key: string]: Subscription | null } = {};

// 通用日志函数
function logToPage(outputId: string, message: any) {
    const outputElement = outputElements[outputId];
    if (outputElement) {
        const timestamp = new Date().toLocaleTimeString();
        outputElement.textContent += `[${timestamp}] ${JSON.stringify(message)}\n`;
        outputElement.scrollTop = outputElement.scrollHeight;
    }
    console.log(`[${outputId}]`, message);
}

// 清空特定输出
function clearOutput(outputId: string) {
    const outputElement = outputElements[outputId];
    if (outputElement) {
        outputElement.textContent = '';
    }
    if (subscriptions[outputId]) {
        subscriptions[outputId]!.unsubscribe();
        subscriptions[outputId] = null;
    }
}

// 清空所有输出
function clearAllOutputs() {
    Object.keys(outputElements).forEach(outputId => {
        clearOutput(outputId);
    });
}

// CombineAll Demo
function runCombineAllDemo() {
    clearOutput('combineAll');
    
    logToPage('combineAll', '=== CombineAll Demo 开始 ===');
    
    const source = interval(1000).pipe(take(2));
    const example = source.pipe(
        map(val => interval(1000).pipe(
            map(i => `Result (${val}): ${i}`), 
            take(3)
        ))
    );
    
    const combined = example.pipe(combineAll());
    
    logToPage('combineAll', '订阅开始，等待数据...');
    
    subscriptions['combineAll'] = combined.subscribe({
        next: val => logToPage('combineAll', val),
        error: err => logToPage('combineAll', `错误: ${err}`),
        complete: () => logToPage('combineAll', '=== CombineAll Demo 完成 ===')
    });
}

// ForkJoin Demo
function runForkJoinDemo() {
    clearOutput('forkJoin');
    
    logToPage('forkJoin', '=== ForkJoin Demo 开始 ===');
    
    const myPromise = (val: string) =>
        new Promise(resolve =>
            setTimeout(() => resolve(`Promise Resolved: ${val}`), 3000)
        );
    
    const example = forkJoin({
        hello: of('Hello'),
        world: of('World').pipe(delay(1000)),
        number: interval(1000).pipe(take(1)),
        sequence: interval(1000).pipe(take(2)),
        promise: myPromise('RESULT')
    });
    
    logToPage('forkJoin', '等待所有 Observable 完成...');
    
    subscriptions['forkJoin'] = example.subscribe({
        next: val => logToPage('forkJoin', val),
        error: err => logToPage('forkJoin', `错误: ${err}`),
        complete: () => logToPage('forkJoin', '=== ForkJoin Demo 完成 ===')
    });
}

// WithLatestFrom Demo
function runWithLatestFromDemo() {
    clearOutput('withLatestFrom');
    
    logToPage('withLatestFrom', '=== WithLatestFrom Demo 开始 ===');
    logToPage('withLatestFrom', '主源每3秒发出值，辅助源每1秒发出值');
    
    // 每3秒发出值（主源）
    const source = interval(5000);
    // 每1秒发出值（辅助源）
    const secondSource = interval(1000);
    
    const example = source.pipe(
        withLatestFrom(secondSource),
        map(([first, second]) => {
            return `主源 (5s): ${first} 辅助源 (1s): ${second}`;
        }),
        take(5) // 只取前5个值以便演示
    );
    
    logToPage('withLatestFrom', '订阅开始，等待数据...');
    
    subscriptions['withLatestFrom'] = example.subscribe({
        next: val => logToPage('withLatestFrom', val),
        error: err => logToPage('withLatestFrom', `错误: ${err}`),
        complete: () => logToPage('withLatestFrom', '=== WithLatestFrom Demo 完成 ===')
    });
}

// Merge Demo
function runMergeDemo() {
    clearOutput('merge');
    
    logToPage('merge', '=== Merge Demo 开始 ===');
    
    const first = interval(2000).pipe(
        map(val => `First: ${val}`),
        take(3)
    );
    
    const second = interval(1000).pipe(
        map(val => `Second: ${val}`),
        take(5)
    );
    
    const third = of('Third: Immediate').pipe(delay(1500));
    
    const merged = merge(first, second, third);
    
    logToPage('merge', '开始合并多个 Observable...');
    
    subscriptions['merge'] = merged.subscribe({
        next: val => logToPage('merge', val),
        error: err => logToPage('merge', `错误: ${err}`),
        complete: () => logToPage('merge', '=== Merge Demo 完成 ===')
    });
}

// ConcatMap Demo
function runConcatMapDemo() {
    clearOutput('concatMap');
    
    logToPage('concatMap', '=== ConcatMap Demo 开始 ===');
    
    const source = of(1, 2, 3);
    
    const example = source.pipe(
        concatMap(val => 
            interval(1000).pipe(
                map(i => `Value ${val} -> ${i}`),
                take(2)
            )
        )
    );
    
    logToPage('concatMap', '开始按顺序处理每个值...');
    
    subscriptions['concatMap'] = example.subscribe({
        next: val => logToPage('concatMap', val),
        error: err => logToPage('concatMap', `错误: ${err}`),
        complete: () => logToPage('concatMap', '=== ConcatMap Demo 完成 ===')
    });
}

// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', () => {
    // 初始化输出元素
    outputElements['combineAll'] = document.getElementById('combineAllOutput')!;
    outputElements['forkJoin'] = document.getElementById('forkJoinOutput')!;
    outputElements['withLatestFrom'] = document.getElementById('withLatestFromOutput')!;
    outputElements['merge'] = document.getElementById('mergeOutput')!;
    outputElements['concatMap'] = document.getElementById('concatMapOutput')!;
    
    // 绑定按钮事件
    document.getElementById('combineAllBtn')?.addEventListener('click', runCombineAllDemo);
    document.getElementById('clearCombineAllBtn')?.addEventListener('click', () => clearOutput('combineAll'));
    
    document.getElementById('forkJoinBtn')?.addEventListener('click', runForkJoinDemo);
    document.getElementById('clearForkJoinBtn')?.addEventListener('click', () => clearOutput('forkJoin'));
    
    document.getElementById('withLatestFromBtn')?.addEventListener('click', runWithLatestFromDemo);
    document.getElementById('clearWithLatestFromBtn')?.addEventListener('click', () => clearOutput('withLatestFrom'));
    
    document.getElementById('mergeBtn')?.addEventListener('click', runMergeDemo);
    document.getElementById('clearMergeBtn')?.addEventListener('click', () => clearOutput('merge'));
    
    document.getElementById('concatMapBtn')?.addEventListener('click', runConcatMapDemo);
    document.getElementById('clearConcatMapBtn')?.addEventListener('click', () => clearOutput('concatMap'));
    
    document.getElementById('clearAllBtn')?.addEventListener('click', clearAllOutputs);
    
    // 初始化消息
    Object.keys(outputElements).forEach(outputId => {
        logToPage(outputId, `${outputId} Demo 已准备就绪`);
    });
});

// 页面卸载时清理所有订阅
window.addEventListener('beforeunload', () => {
    Object.values(subscriptions).forEach(subscription => {
        if (subscription) {
            subscription.unsubscribe();
        }
    });
});